import Koa, {Context} from "koa";
import {routerList, controllerList, paramList, parseList} from "./decorators";
import {httpMethod,paramInterface, parseInterface} from "./decoratorInterface"
import Router from "koa-router";

// 需要导入对应的class,才能自动执行装饰器，获取依赖
import "../controllers/index"
import "../controllers/ContactController"

export const routers: any[] = []
// 遍历所有添加了路由装饰器的class，并创建对应Router对象
routerList.forEach(item => {
    const {baseName, constructor} = item
    // 创建基本路由
    const router = new Router({
        prefix: baseName
    })
    controllerList
        .filter(i => i.target === constructor.prototype)
        .forEach(
            (controller: {
                type: httpMethod,
                path: string,
                method: string,
                controller: Function
            }) => {
                router[controller.type](controller.path,router.allowedMethods(),async (ctx: any, next: Koa.Next) => {
                    let args: any[] = []
                    paramList
                        .filter((param: paramInterface) =>
                            param.target === constructor.prototype &&
                            param.method === controller.method
                        )
                        .map((param: paramInterface) => {
                            const {index, key} = param
                            switch (param.position) {
                                case "body":
                                    args[index] = ctx.request.body[key] ?? ctx.request.body
                                    break
                                case "header":
                                    args[index] = ctx.headers[key] ?? ctx.headers
                                    break
                                case "cookie":
                                    args[index] = ctx.cookies.get(key) ?? ctx.cookies
                                    break
                                case "query":
                                    args[index] = ctx.query[key] ?? ctx.query
                                    break
                                default:
                                    throw "请求的参数不在类型定义中"
                            }
                        })

                    // 当前函数对应的参数格式化
                    parseList
                        .filter(
                            (parse: parseInterface) =>
                                parse.target === constructor.prototype &&
                                parse.method === controller.method
                        )
                        .map((parse: parseInterface) => {
                            const {index} = parse
                            switch (parse.type) {
                                case "number":
                                    args[index] = Number(args[index])
                                    break
                                case "string":
                                    args[index] = String(args[index])
                                    break
                                case "boolean":
                                    args[index] = String(args[index]) === "true"
                                    break
                                default:
                                    throw "数据格式化类型不匹配"
                            }
                        })
                    const myCon = new constructor()
                    // ctx.body = await controller.controller(...args)
                    ctx.body = await myCon[controller.method](...args,ctx,next)??[]
                })
            }
        )
    routers.push(router.routes())
})
